/*************************************************************************
    Field  -  Stocke les différents éléments du terrain
                             -------------------
    début                : Novembre 2011
    copyright            : (C) 2011 SCOR Tournament Project
    e-mail               : jules.lallouette@insa-lyon.fr
*************************************************************************/

//---------- Interface de la classe <VideoSource> (fichier videoSource.h) ------
#if ! defined ( VIDEOSOURCE_H )
#define VIDEOSOURCE_H

//--------------------------------------------------- Interfaces utilisées
using namespace std;
#include <iostream>
#include <list>

#ifdef __APPLE__	// mac
#include <opencv/openCV.h>
#include <opencv/highgui.h>
#endif

#ifdef __linux__	// gcc (egcs) on linux
#include <opencv.hpp>
#include <highgui/highgui.hpp>
#endif

#include "../util.h"
#include "../config.h"
#include "../MsgQueue.h"

using namespace cv;

//------------------------------------------------------------- Constantes
#define SHOW_WINDOWS					1		// Affiche les images filtrees bleu et blanc
#define SHOW_FLUX_VIDEO					1		// Affiche l'image de la webcam avec les robots et la balle
#define CAM_WIDTH						1600	// in pixels
#define CAM_HEIGHT						1200	// in pixels
#define NOMBRE_ITERATION_CLUSTERING		10
#define TAILLE_RECTANGLE_KHEPERA		15		// Taille du robot en pixel
// Tolerance de detection des couleurs.
// Plus la valeur est petite, plus la detection est tolerante
#define COLOR_TOLERANCE_BLUE			20		// Bleu
#define COLOR_TOLERANCE_WHITE			40		// Blanc
#define COLOR_TOLERANCE_GREEN			2		// Vert
#define COLOR_TOLERANCE_RED				100		// Rouge

//------------------------------------------------------------------ Types

struct DataVision
{
	scor::Position posBalle;
	scor::Position posRobots[ROBOT_NUM];
};

typedef struct posKhepera {
	Vec2d position1;
	Vec2d position2;
	Vec2d direction1;
	Vec2d direction2;
} PosKhepera;

//------------------------------------------------------------------------
// Rôle de la classe <VideoSource>
//
//
//------------------------------------------------------------------------

class VideoSource
{
//----------------------------------------------------------------- PUBLIC

public:
//----------------------------------------------------- Méthodes publiques

	bool LancerAnalyse();
	// Mode d'emploi :
	// Lance le thread d'analyse d'image

	int ArreterAnalyse();
	// Mode d'emploi :
	// Arrete le thread d'analyse d'image

    bool InitField();
	// Mode d'emploi :
	// Methode qui lance la fenetre permettant l'initialisation du terrain.


    IplImage * getCurrentFrame();

    bool isAnalyseThreadRunning();
	// Mode d'emploi :
    // Retourne l'etat de lancement ou non du thread

//------------------------------------------------- Surcharge d'opérateurs


//-------------------------------------------- Constructeurs - destructeur

    VideoSource (int largeurTerrain, int longueurTerrain, list<MsgQueue<DataVision>*>& _queueList);
    // Mode d'emploi :
    // Constructeur de VideoSource


    virtual ~VideoSource( );
    // Mode d'emploi :
    // Destructeur de VideoSource


//------------------------------------------------------------------ PRIVE

protected:
//----------------------------------------------------- Méthodes protégées

    PosKhepera trouverNosKheperas(const IplImage * const image, double outlier_threshold);
	// Mode d'emploi :
    // Retourne la position des Kheperas sur l'image passee en parametre
    // La detection des positions des deux robots se fait en effectuant une clusterisation des points bleus de l'image.
    // Ensuite on detecte la direction du robot en prenant le barycentre des points blancs contenu dans
    // un rayon de TAILLE_RECTANGLE_KHEPERA des positions detectees precedemment.

    void on_mouse(int event, int x, int y, int flags);
	// Mode d'emploi :
    // Ajoute le point aux coordonnees x et y dans le tableau des coordonnees du terrain

    void (VideoSource::*mouseCallbackWrapper())(int event, int x, int y, int flags) {
		return &VideoSource::on_mouse;
	}
	// Mode d'emploi :
    //

    Vec2d trouverBalleImage(const Ptr<IplImage> image);
	// Mode d'emploi :
    // Retourne la position de la balle dans l'image passee en parametre
    // La detection de la position de la balle se fait grace au barycentre des points rouge detectes sur l'image.

    bool init(CvCapture* capture);
	// Mode d'emploi :
    // Initialise le thread avec la position des robots et detecte le robot gauche et droite

    void visionThread();
	// Mode d'emploi :
    // Méthode principale du thread


	void (VideoSource::*visionThreadWrapper())() {
		return &VideoSource::visionThread;
	}

private:

    VideoSource();

//------------------------------------------------------- Méthodes privées

protected:
//----------------------------------------------------- Attributs protégés
    // Valeur a initialiser en fonction de la position des robots (a gauche ou a droite)
	int idRobot1;
	int idRobot2;

	// Variables utilisees en phase d'initialisation des coins du terrain
	Vec2d p_corners[4];
	bool waiting_corners;
	int corners;

	// Ce rectangle sert a la conversion des valeurs des positions pour s'adapter
	// a la taille reelle du terrain ou a celle de l'affichage
	Rect_<double> bRect_reel;
	Rect_<double> bRect;
	int width;
	int height;
	CvMat* mmat;

	CvPoint previousBaryCentre_2;
	CvPoint previousBaryCentre_1;
	CvPoint previousBar_1_blanc;
	CvPoint previousBar_2_blanc;

    struct val_st<VideoSource>* visionParams;
    list<MsgQueue<DataVision>*> queueList;
    pthread_t analyseThreadId;
    pthread_mutex_t lockAnalyseThreadLoop;
    bool analyseThreadLoop;

private:
//------------------------------------------------------- Attributs privés


//---------------------------------------------------------- Classes amies

//-------------------------------------------------------- Classes privées

//----------------------------------------------------------- Types privés


};

//----------------------------------------- Types dépendants de <$MODULE$>

#endif // VIDEOSOURCE_H

